package com.example.net.http

import android.util.Log
import com.example.baseutils.*
import com.example.baseutils.Constance.CALL_BASE_URL
import com.example.baseutils.Constance.LOGIN_BASE_URL
import com.example.baseutils.Constance.ROCK_BASE_URL
import com.example.baseutils.Constance.ROCK_DEBUG_BASE_URL
import com.example.baseutils.Constance.SCORE_BASE_URL
import com.example.baseutils.Constance.SPORT_JUMP_AUTO_DEBUG_BASE_URL
import com.example.baseutils.Constance.XIAONUO_BASE_URL
import com.example.baseutils.application.BaseApplication
import com.example.net.http.request.*
import com.example.net.http.response.*
import com.example.net.utils.HttpUtils
import com.example.net.utils.SecurityUtils
import com.google.gson.Gson
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.nio.charset.Charset
import java.util.concurrent.TimeUnit


/**
 * Author by lp,on 2020/8/27/027,11:19.
 * 请求信息
 */
object RetrofitCreator {
    private val TAG = "RetrofitCreator"


    var accessToken = MySharedPreferences.read(Constance.Authorization, "") ?: ""
    var refreshToken = MySharedPreferences.read(Constance.REFRESH_TOKEN, "") ?: ""

    //拦截者
    private val headerInterceptor = Interceptor { chain ->
        val deviceNo =
            AppUtils.getLocalMacAddressFromWifiInfo()
        val request = chain.request().newBuilder().addHeader("deviceNo", deviceNo)
            .addHeader("device_no", deviceNo).build()
        Log.i("RetrofitCreator", "request body $deviceNo: $request")
        val response = chain.proceed(request)
        response
    }


    val httpLoggingInterceptor = HttpLoggingInterceptor().apply {

        level = HttpLoggingInterceptor.Level.BODY
    }

    //okHttpClient
    private val client = OkHttpClient.Builder().addInterceptor(cacheInterceptor())
        .connectTimeout(20, TimeUnit.SECONDS)
        .readTimeout(20, TimeUnit.SECONDS)
//        .retryOnConnectionFailure(true)
        .writeTimeout(20, TimeUnit.SECONDS).build()
    private val logClient = OkHttpClient.Builder().addInterceptor(cacheInterceptor())
        .connectTimeout(20, TimeUnit.SECONDS)
        .readTimeout(20, TimeUnit.SECONDS)
//        .retryOnConnectionFailure(true)
        .writeTimeout(20, TimeUnit.SECONDS).build()

    private val callClient = OkHttpClient.Builder().addInterceptor(cacheInterceptor())
        .addInterceptor(httpLoggingInterceptor)
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
//        .retryOnConnectionFailure(true)
        .writeTimeout(10, TimeUnit.SECONDS)
        .build()

    private val versionRetrofit = Retrofit.Builder()
        .baseUrl(XIAONUO_BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
    private val loginRetrofit = Retrofit.Builder()
        .baseUrl(LOGIN_BASE_URL)
        .client(logClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
    private val scoreRetrofit = Retrofit.Builder()
        .baseUrl(SCORE_BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    private val rockRetrofit = Retrofit.Builder()
        .baseUrl(LOGIN_BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
    private val callRetrofit = Retrofit.Builder()
        .baseUrl(CALL_BASE_URL)
        .client(callClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    private val rockDebugRetrofit = Retrofit.Builder()
        .baseUrl(ROCK_DEBUG_BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
    private val sportJumpAutoDebugRetrofit = Retrofit.Builder()
        .baseUrl(SPORT_JUMP_AUTO_DEBUG_BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    private fun retrofitServiceIml(): RockService {
        return if (MySharedPreferences.read(Constance.DEBUG_MODEL, false))
            debugRockService
        else
            rockService
    }

    private val versionNetService: VerisonNetService =
        versionRetrofit.create(VerisonNetService::class.java)

    val rockService: RockService = rockRetrofit.create(RockService::class.java)
    val callService: CallService = callRetrofit.create(CallService::class.java)
    val loginService: LoginService = loginRetrofit.create(LoginService::class.java)

    val debugRockService: RockService = rockDebugRetrofit.create(RockService::class.java)

    /**
     * 缓存数据拦截器
     *
     * @param mContext Context
     * @param key      秘钥
     */
    private class cacheInterceptor() : Interceptor {
        override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
            val deviceNo =
                AppUtils.getLocalMacAddressFromWifiInfo()
            val request = chain.request().newBuilder()
                .addHeader("deviceNo", deviceNo)
                .addHeader("device_no", deviceNo)
                .addHeader("tenant-id", "151")
                .addHeader("Authorization", "Bearer $accessToken")
                .build()


            val requestBody = request.body
            var body = "null"
            if (requestBody != null) {
                val buffer = Buffer()
                requestBody.writeTo(buffer)
                var charset: Charset = java.nio.charset.StandardCharsets.UTF_8
                body = buffer.readString(charset)
            }
            val requestJson = body
            Log.i(TAG, "cacheInterceptor: requestJson $requestJson")
            if (!requestJson.contains("cacheTime")) {
                val response = chain.proceed(request)
                Log.i(TAG, "非cacheTime: ")
                return response
            }
            val cacheTimeRequest = Gson().fromJson(requestJson, CacheTimeRequest::class.java)
            val cacheTime = cacheTimeRequest.cacheTime * 1000
            // 缓存时间
            val cacheKey = HttpUtils.getCacheKey(request)
            var key = cacheKey
            val cacheFile = File(HttpUtils.getCacheFile(BaseApplication.instance), cacheKey)
            val cacheEnable = (System.currentTimeMillis() - cacheFile.lastModified()) < cacheTime
            if (cacheEnable && cacheFile.exists() && cacheFile.length() > 0) {
                Log.i(
                    TAG,
                    "[intercept] 缓存模式 url:${HttpUtils.getRequestUrl(request)} " + "过期时间:${
                        HttpUtils.dateTimeToString(cacheFile.lastModified() + cacheTime)
                    }"
                )
                val cache = SecurityUtils.decryptContent(cacheFile.readText(), key)
                if (cache.isNotEmpty() && cache.startsWith("{") && cache.endsWith("}")) {
                    Log.i(TAG, "from disk cache: $cache")
                    return okhttp3.Response.Builder()
                        .code(200)
                        .body(cache.toResponseBody())
                        .request(request)
                        .message("from disk cache")
                        .protocol(Protocol.HTTP_2)
                        .build()
                }
            }
            val response = chain.proceed(request)
            //response.body?.string()只能读取一次 就流会被close
            val dataString = response.body?.string() ?: return response
            // 写入缓存
            if (response.code == 200) {
                Log.i(TAG, "-------save cache--------")
                // Json数据写入缓存
                cacheFile.writeText(SecurityUtils.encryptContent(dataString, key))
            } else {
                Log.i(TAG, "-------response error--------" + response.message)
                cacheFile.writeText("")
            }
            return response.newBuilder()
                .message(response.message)
                .body(dataString.toResponseBody(response.body?.contentType()))
                .build()
        }
    }


    //获取版本
    fun getAppVersion(): Response<VersionDataResponse>? {
        val context = BaseApplication.instance.applicationContext
        val request = AppVersionReuqst(
            "高拍仪",
            505,
            AppUtils.getAppVersionName(context),
            AppUtils.getLocalMacAddressFromWifiInfo()
        )
        val requestJson = Gson().toJson(request)
        Log.i(TAG, requestJson)
        val requestBody =
            RequestBody.create("application/json;charset=utf-8".toMediaTypeOrNull(), requestJson)

        val call = versionNetService.getAppVersion(requestBody)
        try {
            val result = call.execute()
            "getAppVersion result ${result.isSuccessful}".log(TAG)
            "getAppVersion result ${result?.body()?.data}".log(TAG)
            "getAppVersion result ${result.toString()}".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return null

    } //获取版本

    suspend fun queryRank(gameId: String): BaseResponse<List<RankResponse>>? {
        Log.i(TAG, "queryRank gameId $gameId  ")
        try {
            val result = rockService.queryRank(gameId)
            "uploadRank result ${result.success}".log(TAG)
            "uploadRank result ${result?.data}".log(TAG)
            "uploadRank result ${result.toString()}".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }


    //获取版本
    suspend fun getUserNum(roomId: String): BaseResponse<RoomUserResponse>? {
        Log.i(
            TAG,
            "getUserNum roomId $roomId refreshToken $refreshToken   accessToken  $accessToken"
        )
        try {
            val result = rockService.getLiveUser(roomId)
            "getUserNum result ${result.success}".log(TAG)
            "getUserNum result ${result?.data}".log(TAG)
            "getUserNum result ${result.toString()}".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 发送短信验证码 scene：24 是固定的
     * */
    suspend fun sendSms(phone: String): BaseLoginResponse<Any> {
        Log.i(TAG, "sendSms: phone $phone ")
        val errorResponse = BaseLoginResponse<Any>()
        errorResponse.success = false
        try {
            val requestJson = "{" +
                    "\"scene\":24" +
                    "," +
                    "\"mobile\":$phone" +
                    "}"
            Log.i(TAG, "sendSms $requestJson")
            val requestBody =
                RequestBody.create(
                    "application/json;charset=utf-8".toMediaTypeOrNull(),
                    requestJson
                )
            val result = loginService.sendSms(requestBody)
            "sendSms result $result".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
            errorResponse.message = e.message
        }
        return errorResponse
    }

    suspend fun visitation(code: String): BaseLoginResponse<VisitationResponse> {
        "visitation $code  $accessToken".log(TAG)
        val errorResponse = BaseLoginResponse<VisitationResponse>()
        return try {
            val result = loginService.visitation(code)
            "visitation 发送信息是否成功 $result".log(TAG)
            result
        } catch (e: Exception) {
            e.printStackTrace()
            "message ${e.message}".log(TAG, LogUtils.LogLevel.E)
            errorResponse.message = e.message
            errorResponse
        }
        return errorResponse
    }

    /**
     * 刷新token
     * */
    suspend fun refreshToken(): BaseLoginResponse<LoginResponse> {
        Log.i(TAG, "refreshToken:  $refreshToken ")
        val errorResponse = BaseLoginResponse<LoginResponse>()
        errorResponse.success = false
        try {
            val result = loginService.refreshToken(refreshToken)
            "refreshToken result $result".log(TAG)
            if (result.success == true && result.code == "0" && result.data?.accessToken != null)
                saveToken(result.data?.accessToken!!, result.data?.refreshToken!!)
            else
                result.success = false
            return result
        } catch (e: Exception) {
            e.printStackTrace()
            errorResponse.message = e.message
        }
        return errorResponse
    }

    /**
     * 根据验证码 code登录
     * @param smsCode 验证码
     * @param phone 手机号
     * @return 返回  {
    "userId": 247,
    "accessToken": "1b7847c8fc2943e9b92e0f2bd417d67d",
    "refreshToken": "7cbc17198636441db137e7be01ab2307",
    "expiresTime": 1731742307563
    }
     *
     * */
    suspend fun registerLogin(phone: String, smsCode: String): BaseLoginResponse<LoginResponse> {
        Log.i(TAG, "registerLogin: phone $phone ")
        val errorResponse = BaseLoginResponse<LoginResponse>()
        errorResponse.success = false
        try {
            val requestJson = "{" +
                    "\"code\": \"$smsCode\"" +
                    "," +
                    "\"mobile\": \"$phone\"" +
                    "}"
            Log.i(TAG, "registerLogin $requestJson")
            val requestBody =
                RequestBody.create(
                    "application/json;charset=utf-8".toMediaTypeOrNull(),
                    requestJson
                )
            val result = loginService.registerLogin(requestBody)
            if (result.code == "0" && result.data?.accessToken != null) {
                saveToken(result.data?.accessToken!!, result.data?.refreshToken!!)
            }
            "registerLogin result $result".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
            errorResponse.message = e.message
        }
        return errorResponse
    }

    suspend fun updateAvatar(avatarUrl: String, nickName: String): BaseLoginResponse<String> {
        Log.i(TAG, "updateAvatar:  ")
        val errorResponse = BaseLoginResponse<String>()
        errorResponse.success = false
        try {
            val requestJson = "{" +
                    "    \"avatarUrl\": \"$avatarUrl\"," +
                    "    \"nickName\": \"$nickName\"" +
                    "}"
            Log.i(TAG, "updateAvatar $requestJson")
            val requestBody =
                RequestBody.create(
                    "application/json;charset=utf-8".toMediaTypeOrNull(),
                    requestJson
                )
            val result = loginService.updateAvatar(requestBody)
            "updateAvatar result $result".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
            errorResponse.message = e.message
        }
        return errorResponse
    }


    suspend fun getToken(request: RtcTokenRequest): BaseResponse<String> {
        Log.i(TAG, "getToken: $request ")
        val errorResponse = BaseResponse<String>()
        errorResponse.success = false
        try {
            val requestJson = Gson().toJson(request)
            Log.i(TAG, "getToken  requestJson $requestJson")
            val requestBody =
                RequestBody.create(
                    "application/json;charset=utf-8".toMediaTypeOrNull(),
                    requestJson
                )
            val result = loginService.getRtcToken(requestBody)
            "requestJson result $result".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
            errorResponse.message = e.message
        }
        return errorResponse
    }


    private fun saveToken(token: String, reToken: String) {
        if (accessToken == token && refreshToken == reToken) {
            Log.e(TAG, "saveToken: 无需更新")
            return
        }
        accessToken = token
        refreshToken = reToken
        Log.e(TAG, "saveToken 更新accessToken $accessToken")
        Log.e(TAG, "saveToken: 更新refresh_token $refreshToken")
        MySharedPreferences.save {
            putString(Constance.Authorization, accessToken)
            putString(Constance.REFRESH_TOKEN, refreshToken)
        }

    }

    /**
     *
     * 发送呼叫请求
     * */
    suspend fun sendCall(userId: String, roomId: String): BaseResponse<String?> {
        Log.i(TAG, "sendCall before ")
        val request = CallSendRequest()
        Log.i(TAG, "sendCall: $request ")
        val errorResponse = BaseResponse<String?>()
        errorResponse.success = false
        try {
            val requestJson = Gson().toJson(request)
            Log.i(TAG, "sendCall  requestJson $requestJson")
            val requestBody =
                RequestBody.create(
                    "application/json;charset=utf-8".toMediaTypeOrNull(),
                    requestJson
                )
            val result = callService.sendCall(requestBody, roomId, userId)
            "sendCall result $result".log(TAG)
            return result
        } catch (e: Exception) {
            e.printStackTrace()
            errorResponse.message = e.message
        }
        return errorResponse
    }


}

